/*
** server.c for  in /home/jousse_f//workspace/SysUnix/ftp
** 
** Made by florian jousseau
** Login   <jousse_f@epitech.net>
** 
** Started on  Mon Apr  2 16:38:01 2012 florian jousseau
** Last update Wed Apr  4 15:53:24 2012 florian jousseau
*/

#include "server.h"

t_cmd	tab[] =
  {
    {"ls", &ls},
    {"cd", &cd},
    {"pwd", &pwd},
    {"quit", &quit},
    {"get", &get},
    {"put", &put},
    {"z", NULL},
  };

int		work(char *buf, int cs)
{
  int		i;
  int		ret;

  i = 0;
  while (strncmp(buf, tab[i].str, strlen(tab[i].str)) != 0 &&
	 strcmp(tab[i].str, "z") != 0)
    i++;
  if (tab[i].ptr != NULL)
    ret = tab[i].ptr(buf, cs);
  write(cs, "Command executed\n", strlen("Command executed\n"));
  return (ret);
}

void		do_client(int cs, int cont)
{
  int		len;
  char		*buf;

  buf = malloc(sizeof(char) * 512);
  cont = 0;
  while (cont == 0)
    {
      len = read(cs, buf, 512);
      if (len > 0)
	{
	  buf[len] = '\0';
	  cont = work(buf, cs);
	}
      else if (len <= 0)
	{
	  cont = 1;
	  printf("\033[31;01mClient\033[00m : %s\n-> this client has left the server\n", buf);
	}
    }
  free(buf);
}

void			run(int sockfd, struct sockaddr_in sin_client)
{
  int			client_len;
  char			*str;
  int			cs;
  int			pnum;

  client_len = sizeof(sin_client);
  while (1)
    {
      cs = xaccept(sockfd, (struct sockaddr *)&sin_client, (socklen_t *)&client_len);
      if ((pnum = fork ()) == 0)
	{
	  str = inet_ntoa(sin_client.sin_addr);
	  printf("Connection on %s success\n", str);
	  write(cs, "Connexion to the serveur successfull\n", 38);
	  do_client(cs, 0);
	}
      if (pnum > 0)
	close(cs);
      if (pnum == -1)
	{
	  perror ("fork");
	  exit(1);
	}
    }
}

int			main(int ac, char **av)
{
  struct protoent	*pe;
  struct sockaddr_in	sin;
  struct sockaddr_in	sin_client;
  int			sockfd;
  int			port;

  if (ac != 2)
    exit(EXIT_FAILURE);
  port = atoi(av[1]);
  pe = getprotobyname("TCP");
  sockfd = xsocket(AF_INET, SOCK_STREAM, pe->p_proto);
  sin.sin_family = AF_INET;
  sin.sin_port = htons(port);
  sin.sin_addr.s_addr = INADDR_ANY;
  xbind(sockfd, (const struct sockaddr *)&sin, sizeof(sin));
  xlisten(sockfd, 42);
  run(sockfd, sin_client);
  close(sockfd);
  return (EXIT_SUCCESS);
}
